<template>
  <div class="bpmn-page">
    <div :id="bpmnID" class="modeler-container" />
  </div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, watch, onBeforeUnmount } from 'vue'
import translate from './zh'
import createDefaultBpmnXml from './defaultBpmnXml'
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
import paletteProvider from './bpnm-utils/palette-provider.js'
import CustomContextPadProvider from './bpnm-utils/custom-context-pad-provider.js'
import { BPMN } from './bpmn'
// camunda描述json
import camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda'

interface Props {
  bpmnID: string | undefined
  isReadOnly?: boolean
  options?: any
  operation?: any
}
const props = withDefaults(defineProps<Props>(), {
  bpmnID: 'modeler-container',
  isReadOnly: false,
  options: {},
  operation: []
})
const defaultProcessIdAndName = '1'
const emits = defineEmits(['select:element', 'data:change'])
const bpmnStore = ref(
  new BPMN({
    dataChange: (_oldVal: any, newVal: any) => {
      emits('data:change', { businessObject: newVal })
    }
  })
)

const state = reactive({
  operation: [
    {
      label: '导入XML',
      icon: '#icon-shangchuan',
      action: importXML
    },
    {
      label: '导出XML',
      icon: '#icon-zu1359',
      action: exportXML
    },
    {
      label: '导出SVG',
      icon: '#icon-zu920',
      action: () => {
        bpmnStore.value.exportSVG()
      }
    },
    {
      label: '放大',
      icon: '#icon-fangda',
      action: () => {
        state.zoom = Math.floor(state.zoom * 100 + 0.1 * 100) / 100
        bpmnStore.value.getModeler().get('canvas').zoom(state.zoom)
      }
    },
    {
      label: '缩小',
      icon: '#icon-suoxiao',
      action: () => {
        state.zoom = Math.floor(state.zoom * 100 - 0.1 * 100) / 100
        bpmnStore.value.getModeler().get('canvas').zoom(state.zoom)
      }
    },
    {
      label: '还原并居中',
      icon: '#icon-quxiaoquanping',
      action: () => {
        state.zoom = 1
        bpmnStore.value.getModeler().get('canvas').zoom('fit-viewport', 'auto')
      }
    }
  ],
  zoom: 1
})

onMounted(() => {
  if (props.isReadOnly) {
    bpmnStore.value.initModeler({
      container: `#${props.bpmnID}`,
      additionalModules: [
        //添加翻译
        {
          translate: ['value', translate()],
          paletteProvider: ['value', ''], //禁用/清空左侧工具栏
          labelEditingProvider: ['value', ''], //禁用节点编辑
          contextPadProvider: ['value', ''], //禁用图形菜单
          bendpoints: ['value', {}], //禁用连线拖动
          zoomScroll: ['value', ''], //禁用滚动
          moveCanvas: ['value', ''], //禁用拖动整个流程图
          move: ['value', ''] //禁用单个图形拖动
        }
      ],
      moddleExtensions: {
        camunda: camundaModdleDescriptor
      },
      ...props.options
    })
  } else {
    bpmnStore.value.initModeler({
      container: `#${props.bpmnID}`,
      additionalModules: [
        //添加翻译
        { translate: ['value', translate()] },
        // customPalette,
        paletteProvider,
        CustomContextPadProvider
        // customContextPad,
        // customRender,
      ],
      moddleExtensions: {
        camunda: camundaModdleDescriptor
      },
      ...props.options
    })
  }
  bpmnStore.value
    //@ts-ignore
    .importXML(createDefaultBpmnXml(defaultProcessIdAndName, defaultProcessIdAndName))
    .then((result: Array<string>) => {
      if (result.length) {
        console.warn('importSuccess warnings', result)
      }
    })
    .catch((err: any) => {
      console.warn('importFail errors ', err)
    })
  if (props.operation.length) {
    state.operation = props.operation
  }
})
watch(
  () => bpmnStore.value.activeElementID,
  (_newVal) => {
    if (!bpmnStore.value.getShapeById(bpmnStore.value.activeElementID)) {
      bpmnStore.value.setActiveElement(undefined)
      bpmnStore.value.setType(undefined)
      return
    }
    const businessObject = bpmnStore.value.getBusinessObject() || undefined
    emits('select:element', {
      businessObject,
      shapeType: bpmnStore.value.getShapeType()
    })
  },
  {
    deep: true
  }
)

onBeforeUnmount(() => {
  bpmnStore.value.resetData()
})

function exportXML() {
  bpmnStore.value.exportXML()
}

function importXML() {
  const fileUpload: any = document.createElement('input')
  fileUpload.type = 'file'
  fileUpload.click()
  fileUpload.onchange = () => {
    const file = fileUpload.files[0]
    const reader = new FileReader()
    reader.onload = () => {
      const xml: any = reader.result
      bpmnStore.value.importXML(xml)
    }
    reader.readAsText(file)
  }
}

defineExpose({
  bpmnStore
})
</script>
<style scoped lang="scss">
.bpmn-page {
  width: 100%;
  height: 100%;
  position: relative;
}

.bjs-powered-by {
  display: none;
}

.bpmn-container {
  height: 100%;
}

.modeler-container {
  position: relative;
  flex: 1;
  height: 100%;
  background: url('')
    repeat !important;
}

.djs-palette {
  top: 65px !important;
  border: none !important;
  background-color: #fff !important;
  box-shadow: 0 3px 3px rgb(0 0 0 / 20%);
}

:deep(.djs-palette.two-column.open) {
  width: 47px !important;
}

.icon-custom {
  /* 定义一个公共的类名 */
  border-radius: 50%;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 65%;
}

:deep(.icon-custom.lindaidai-task) {
  width: 30px;
  height: 30px;
  margin: 8px;

  /* 加上背景图 */
  background: url('https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/rules.png') no-repeat;
  background-size: 100% 100%;
}

:deep(.djs-context-pad) .lindaidai-task.entry:hover {
  background: url('https://hexo-blog-1256114407.cos.ap-shenzhen-fsi.myqcloud.com/rules.png') no-repeat;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 95%;
}

:deep(.djs-context-pad) .entry:hover {
  /* 重新修改了 hover 之后的样式 */

  /* border: 1px solid #1890ff; */
  box-sizing: border-box;
}

:deep(.djs-context-pad) .entry {
  box-sizing: border-box;
  transition: all 0.3s;
  background-size: 94%;
}

.default-input {
  margin-bottom: 10px;
}

.bpmn-operation {
  position: absolute;
  bottom: 2%;
  left: 1%;
  display: flex;
  justify-content: space-evenly;
  align-items: center;

  svg {
    width: 30px;
    height: 30px;
    margin-right: 16px;
    cursor: pointer;
  }
  // background-color: red;
}
</style>
